#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

using namespace std;

//可变参数
void ShowList()
{
    cout << endl;
}

template<class T, class...Args>
void ShowList(T t, Args...args)
{
    cout << t << " ";
    ShowList(args...);
}

template<class...Args>
void function(Args...args)
{
    cout << "解析中。。。共有：" << endl;
    cout << sizeof...(args) << endl;
    cout << ">" << " ";
    ShowList(args...);
}

char* newnew = (char*)"1234567890";

int main()
{
    //程序替换中，并没有创建新的进程，只是将当前进程的代码和数据用新的程序的代码
    //和数据进行覆盖式的替换；一旦程序替换成功，就去执行源代码了，源代码的后半部分
    //已经被替换了；execl只有错误时才返回值，返回-1，exed*函数都是这个特点，就像
    //一个加载器一样；
    //----------------------------------------------------------------
    //execlp，不需要写文件路径，直接写操作名即可，这里的P相当于PATH的意思，但此
    //函数的缺点是不太能执行自己写的文件
    //----------------------------------------------------------------
    //execv(const char* file, char* const argv[])，提供一个命令行参数表，就是一个
    //指针数组
    //----------------------------------------------------------------
    //execvp，不需要传路径，然后传指令的指针数组
    //----------------------------------------------------------------
    //execvpe，不需要传路径，传指令指针数组，传环境变量指针数组
    //----------------------------------------------------------------
    //putenv(char* string)，谁调用它，就给谁新增环境变量，但是要定义全局的
    //----------------------------------------------------------------
    //execve是系统调用，以上各种exec*都是对它的语言级别的封装
    //function(1, 2, 3, 4, 5, 5);
    //sleep(10);
    putenv(newnew);
    cout << "我的程序开始运行了" << endl;
    if(fork() == 0)
    {
    cout << "子进程开始运行" << endl;
    char* const env[] = 
    {
        (char* const)"MYENV = 1234454",
        (char* const)"-a",
        (char* const)"-b",
        NULL
    };

    char* const argv[] = 
    {
        (char* const)"./code",
        NULL
    };
    
    extern char** environ;

    sleep(3);
    //这样就获得了用子进程打印所传环境变量的方法
    int n = execvpe("./a.out", argv, environ);
    sleep(10);
    exit(0);
    }
    //为什么没有影响父进程？进程具有独立性，而且数据发生写实拷贝
    waitpid(-1, nullptr, 0);
    cout << "我的程序运行完毕"<< endl;
    return 0;

    //execl(路径+程序名const char* PATH, ...(可变参数)——命令行怎么写就整么传)
    //执行谁？怎么执行他？（参数必须以null结尾，一表示参数传递完成
}
